package cool.mtc.io.zip;

import cool.mtc.core.util.StringUtil;
import cool.mtc.io.util.ResourceUtil;
import cool.mtc.io.zip.exception.ZipException;
import lombok.Cleanup;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Files;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @author yz
 */
@Component
public class ZipTemplate {

    public File zip(String sourceFilePath, String targetFilePath) {
        return this.zip(sourceFilePath, targetFilePath, null);
    }

    public File zip(String sourceFilePath, String targetFilePath, String nodeName) {
        try {
            File sourceFile = ResourceUtil.getResource(sourceFilePath).getFile();
            File targetFile = ResourceUtil.createResource(targetFilePath).getFile();
            @Cleanup ZipOutputStream zipOutputStream = new ZipOutputStream(Files.newOutputStream(targetFile.toPath()));
            this.zip(sourceFile, zipOutputStream, nodeName);
            return targetFile;
        } catch (IOException ex) {
            throw new ZipException("创建文件压缩包失败", ex);
        }
    }

    /**
     * 压缩文件
     *
     * @param sourceFile      要压缩的文件或文件夹
     * @param zipOutputStream 生成的zip文件输出流
     * @param nodeName        压缩后节点名称
     */
    public void zip(File sourceFile, ZipOutputStream zipOutputStream, String nodeName) {
        String zipNodeName = StringUtil.isEmpty(nodeName) ? sourceFile.getName() : nodeName;
        if (sourceFile.isFile()) {
            // 处理文件
            try {
                zipOutputStream.putNextEntry(new ZipEntry(zipNodeName));
                @Cleanup FileInputStream inputStream = new FileInputStream(sourceFile);
                // copy文件到zip输出流中
                IOUtils.copy(inputStream, zipOutputStream);
                zipOutputStream.closeEntry();
            } catch (FileNotFoundException ex) {
                String errMsg = String.format("源文件[%s]未找到", sourceFile.getAbsolutePath());
                throw new ZipException(errMsg);
            } catch (IOException ex) {
                throw new ZipException("创建文件压缩包失败", ex);
            }
        } else {
            // 处理文件夹
            File[] files = sourceFile.listFiles();
            if (null == files || files.length == 0) {
                try {
                    zipOutputStream.putNextEntry(new ZipEntry(zipNodeName + "/"));
                    zipOutputStream.closeEntry();
                } catch (IOException ex) {
                    throw new ZipException("创建文件压缩包失败", ex);
                }
            } else {
                for (File file : files) {
                    zip(file, zipOutputStream, zipNodeName + "/" + file.getName());
                }
            }
        }
    }
}
